package com.bocloud.cmp.driver.providers.ali;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.ecs.model.v20140526.CreateInstanceRequest;
import com.aliyuncs.ecs.model.v20140526.CreateInstanceResponse;
import com.aliyuncs.ecs.model.v20140526.CreateSnapshotRequest;
import com.aliyuncs.ecs.model.v20140526.CreateSnapshotResponse;
import com.aliyuncs.ecs.model.v20140526.DeleteInstanceRequest;
import com.aliyuncs.ecs.model.v20140526.DeleteInstanceResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesResponse.Instance;
import com.aliyuncs.ecs.model.v20140526.JoinSecurityGroupRequest;
import com.aliyuncs.ecs.model.v20140526.JoinSecurityGroupResponse;
import com.aliyuncs.ecs.model.v20140526.LeaveSecurityGroupRequest;
import com.aliyuncs.ecs.model.v20140526.LeaveSecurityGroupResponse;
import com.aliyuncs.ecs.model.v20140526.RebootInstanceRequest;
import com.aliyuncs.ecs.model.v20140526.RebootInstanceResponse;
import com.aliyuncs.ecs.model.v20140526.StartInstanceRequest;
import com.aliyuncs.ecs.model.v20140526.StartInstanceResponse;
import com.aliyuncs.ecs.model.v20140526.StopInstanceRequest;
import com.aliyuncs.ecs.model.v20140526.StopInstanceResponse;
import com.aliyuncs.exceptions.ClientException;
import com.bocloud.cmp.driver.providers.ServerDriver;
import com.bocloud.cmp.model.OSMigrateModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.utils.DateTools;
import com.bocloud.common.utils.KeyGenerator;
import com.google.common.collect.Lists;

public class AliEcsDriver extends AliDriver implements ServerDriver {

	private static final int PAGE_SIZE = 100;
	private static Logger logger = LoggerFactory.getLogger(AliEcsDriver.class);

	/**
	 * 
	 */
	public AliEcsDriver() {
		super();
	}

	/**
	 * @param accessKey
	 * @param secretKey
	 * @param regionId
	 */
	public AliEcsDriver(String accessKey, String secretKey, String regionId) {
		super(accessKey, secretKey, regionId);
	}

	@Override
	public BsmResult create(ServerModel server) {
		CreateInstanceRequest request = new CreateInstanceRequest();
		request.setRegionId(this.getRegionId());
		request.setZoneId(server.getZone());
		request.setImageId(server.getImageId());
		request.setInstanceName(server.getName());
		request.setInstanceType(server.getInstanceType());
		request.setInternetChargeType(server.getInstanceChargeType());
		request.setPassword(server.getPassword());
		request.setDescription(server.getRemark());
		request.setHostName(server.getName());
		request.setSecurityGroupId(server.getSecurityGroupId());
		request.setSystemDiskCategory(server.getSystemDiskCategory());
		request.setSystemDiskSize(Integer.valueOf(server.getSystemDiskSize()));
		request.setInternetMaxBandwidthIn(server.getInternetMaxBandwidthIn());
		request.setInternetMaxBandwidthOut(server.getInternetMaxBandwidthOut());
		if (StringUtils.hasText(server.getDataDisk())) {
			logger.info(server.getDataDisk());
			JSONArray dataDisks = JSONArray.parseArray(server.getDataDisk());
			int diskSize = dataDisks.size();
			if (diskSize > 0) {
				for (int i = 0; i < diskSize; i++) {
					setDataDisk(i + 1, dataDisks.getJSONObject(i), request);
				}
			}
		}
		request.setClientToken(KeyGenerator.uuid());
		try {
			CreateInstanceResponse response = this.getClient().getAcsResponse(request);
			String instanceId = response.getInstanceId();
			if (StringUtils.isEmpty(instanceId)) {
				return new BsmResult(false, "创建失败！");
			} else {
				return new BsmResult(true, detail(instanceId).getData(), "success");
			}
		} catch (ClientException e) {
			logger.error("create instance [{}] error:[{}]", JSONObject.toJSONString(server), e);
			return new BsmResult(false, e.getErrMsg(), "创建失败！");
		}
	}

	private void setDataDisk(Integer diskNum, JSONObject disk, CreateInstanceRequest request) {
		switch (diskNum) {
		case 1:
			request.setDataDisk1Category(disk.getString("dataDiskCategory"));
			request.setDataDisk1DeleteWithInstance(true);
			request.setDataDisk1Size(disk.getInteger("dataDiskSize"));
			break;
		case 2:
			request.setDataDisk2Category(disk.getString("dataDiskCategory"));
			request.setDataDisk2DeleteWithInstance(true);
			request.setDataDisk2Size(disk.getInteger("dataDiskSize"));
			break;
		case 3:
			request.setDataDisk3Category(disk.getString("dataDiskCategory"));
			request.setDataDisk3DeleteWithInstance(true);
			request.setDataDisk3Size(disk.getInteger("dataDiskSize"));
			break;
		case 4:
			request.setDataDisk4Category(disk.getString("dataDiskCategory"));
			request.setDataDisk4DeleteWithInstance(true);
			request.setDataDisk4Size(disk.getInteger("dataDiskSize"));
			break;
		default:
			break;
		}
	}

	@Override
	public BsmResult start(String instanceId) {
		StartInstanceRequest startInstanceRequest = new StartInstanceRequest();
		startInstanceRequest.setInstanceId(instanceId);
		StartInstanceResponse response;
		try {
			response = this.getClient().getAcsResponse(startInstanceRequest);
			return new BsmResult(true, response.getRequestId(), "主机启动中");
		} catch (ClientException e) {
			logger.error("start instance [{}] error:", instanceId, e);
			return new BsmResult(false, "主机启动失败！", e.getErrMsg());
		}
	}

	@Override
	public BsmResult stop(String instanceId) {
		StopInstanceRequest stopInstanceRequest = new StopInstanceRequest();
		stopInstanceRequest.setInstanceId(instanceId);
		StopInstanceResponse response;
		try {
			response = this.getClient().getAcsResponse(stopInstanceRequest);
			return new BsmResult(true, response.getRequestId(), "主机关闭中");
		} catch (ClientException e) {
			logger.error("stop instance [{}] error:", instanceId, e);
			return new BsmResult(false, "主机停止失败！", e.getErrMsg());
		}
	}

	@Override
	public BsmResult reboot(String instanceId) {
		RebootInstanceRequest rebootInstanceRequest = new RebootInstanceRequest();
		rebootInstanceRequest.setInstanceId(instanceId);
		try {
			RebootInstanceResponse response = this.getClient().getAcsResponse(rebootInstanceRequest);
			return new BsmResult(true, response.getRequestId(), "主机重启中");
		} catch (ClientException e) {
			logger.error("reboot instance [{}] error:", instanceId, e);
			return new BsmResult(false, "主机重启失败！", e.getErrMsg());
		}
	}

	@Override
	public BsmResult remove(String instanceId) {
		DeleteInstanceRequest deleteInstanceRequest = new DeleteInstanceRequest();
		deleteInstanceRequest.setInstanceId(instanceId);
		try {
			DeleteInstanceResponse response = this.getClient().getAcsResponse(deleteInstanceRequest);
			return new BsmResult(true, response.getRequestId(), "主机释放中");
		} catch (ClientException e) {
			logger.error("remove instance [{}] error:", instanceId, e);
			return new BsmResult(false, "主机释放失败！", e.getErrMsg());
		}
	}

	@Override
	public BsmResult list() {
		DescribeInstancesRequest describe = new DescribeInstancesRequest();
		describe.setPageNumber(1);
		describe.setPageSize(PAGE_SIZE);// 因为阿里云最大的页码大小是100
		List<ServerModel> models = Lists.newArrayList();
		try {
			DescribeInstancesResponse response = this.getClient().getAcsResponse(describe);
			List<Instance> instances = response.getInstances();
			int totalCount = response.getTotalCount();
			if (totalCount == 0) {
				return new BsmResult(true, models, "empty servers");
			}
			for (Instance instance : instances) {
				models.add(this.convertServer(instance));
			}
			int totalPage = totalCount / PAGE_SIZE + 1;
			if (totalPage == 1) {
				return new BsmResult(true, models, "success");
			}
			for (int i = 2; i <= totalPage; i++) {
				describe.setPageNumber(i);
				describe.setPageSize(PAGE_SIZE);
				response = this.getClient().getAcsResponse(describe);
				instances = response.getInstances();
				for (Instance instance : instances) {
					models.add(this.convertServer(instance));
				}
			}
			return new BsmResult(true, models, "success");
		} catch (ClientException e) {
			logger.error("get instances error:", e);
			return new BsmResult(false, "获取主机信息失败！");
		}
	}

	@Override
	public BsmResult detail(String instanceId) {
		DescribeInstancesRequest request = new DescribeInstancesRequest();
		JSONArray instanceIds = new JSONArray(1);
		instanceIds.add(instanceId);
		request.setInstanceIds(instanceIds.toJSONString());
		try {
			DescribeInstancesResponse response = this.getClient().getAcsResponse(request);
			List<Instance> instances = response.getInstances();
			int totalCount = response.getTotalCount();
			if (totalCount == 0) {
				return new BsmResult(false, "实例不存在");
			}
			return new BsmResult(true, convertServer(instances.get(0)), "success");
		} catch (ClientException e) {
			logger.error("get instances error:", e);
			return new BsmResult(false, "获取主机信息失败！");
		}
	}

	@Override
	public BsmResult joinSGroup(String serverId, String groupId) {
		JoinSecurityGroupRequest joinSecurityGroupRequest = new JoinSecurityGroupRequest();
		joinSecurityGroupRequest.setInstanceId(serverId);
		joinSecurityGroupRequest.setSecurityGroupId(groupId);
		try {
			JoinSecurityGroupResponse response = this.getClient().getAcsResponse(joinSecurityGroupRequest);
			return new BsmResult(true, response.getRequestId(), "操作成功！");
		} catch (ClientException e) {
			logger.error("instance [{}] join securitygroup [{}] error:", serverId, groupId, e);
			return new BsmResult(true, e.getMessage(), "操作失败！");
		}
	}

	@Override
	public BsmResult leaveSGroup(String serverId, String groupId) {
		LeaveSecurityGroupRequest leaveSecurityGroupRequest = new LeaveSecurityGroupRequest();
		leaveSecurityGroupRequest.setInstanceId(serverId);
		leaveSecurityGroupRequest.setSecurityGroupId(groupId);
		try {
			LeaveSecurityGroupResponse response = this.getClient().getAcsResponse(leaveSecurityGroupRequest);
			return new BsmResult(true, response.getRequestId(), "操作成功！");
		} catch (ClientException e) {
			logger.error("instance [{}] leave securitygroup [{}] error:", serverId, groupId, e);
			return new BsmResult(true, e.getMessage(), "操作失败！");
		}
	}

	private ServerModel convertServer(Instance instance) {
		if (null == instance) {
			return null;
		}
		ServerModel server = new ServerModel();
		server.setCpu(instance.getCpu());
		server.setImageId(instance.getImageId());
		server.setInstanceId(instance.getInstanceId());
		server.setMemory(instance.getMemory());
		server.setName(instance.getInstanceName());
		server.setAccount("root");
		server.setPrivateIps(JSONObject.toJSONString(instance.getInnerIpAddress()));
		server.setPublicIps(JSONObject.toJSONString(instance.getPublicIpAddress()));
		server.setSecurityGroupId(JSONObject.toJSONString(instance.getSecurityGroupIds()));
		server.setGmtCreate(DateTools.transfer("yyyy-MM-dd'T'HH:mmZ", instance.getCreationTime(), "Z"));
		server.setRemark(instance.getDescription());
		server.setStatus(instance.getStatus().name().toUpperCase());
		server.setUuid(instance.getSerialNumber());
		return server;
	}

	@Override
	public BsmResult modify(ServerModel server) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BsmResult migrate(ServerModel server) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BsmResult OSMigrate(OSMigrateModel OSMigrate) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BsmResult snapshot(SnapshotModel model) {
		CreateSnapshotRequest request = new CreateSnapshotRequest();
		request.setDescription(model.getRemark());
		request.setDiskId(model.getVolumeId());
		request.setSnapshotName(model.getName());
		try {
			CreateSnapshotResponse response = this.getClient().getAcsResponse(request);
			return new BsmResult(true, response.getRequestId());
		} catch (ClientException e) {
			logger.error("create snapshot [{}] error:", model.getName(), e);
			return new BsmResult(false, "");
		}
	}

	@Override
	public BsmResult suspend(String instanceId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BsmResult VncConsole(String vncType, String serverId) {
		// TODO Auto-generated method stub
		return null;
	}

    @Override
    public BsmResult resume(String instanceId) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public BsmResult unpause(String instanceId) {
        // TODO Auto-generated method stub
        return null;
    }

}
